using System;
using System.Collections.Generic;

using SBPweb.Common.Authorization;
using SBPweb.Common.Caching;
using SBPweb.Common.Session;

using SBPweb.PROvibe.Resources.Warehouse.Template;

using SBPweb.PROvibe.Business.Logic;

namespace SBPweb.PROvibe.Business.Warehouse
{
	public class TemplateFactory
	{

		#region Private static string constants

		private static string CACHEKEY_TEMPLATES = "Warehouse.Templates";
		private static string CACHEKEY_TEMPLATES_INDEX_ID = "Warehouse.Templates.Index.Id";
		private static string CACHEKEY_TEMPLATES_INDEX_NAME = "Warehouse.Templates.Index.Name";

		private static string SESSIONKEY_TEMPLATES = "_Repository.Templates";

		#endregion

		#region Private fields

		private static TemplateRepository mTemplateRepository
		{
			get
			{
				TemplateRepository ret = SessionHandler.Get<TemplateRepository>(SESSIONKEY_TEMPLATES);

				if (ret == null)
				{
					ret = new TemplateRepository(ConfigurationManager.ConnectionStrings.Warehouse);
					SessionHandler.Put<TemplateRepository>(SESSIONKEY_TEMPLATES, ret);
				}

				return ret;
			}
		}

		#endregion

		#region Constructor logic

		private TemplateFactory()
		{
		}

		#endregion

		#region Repository handler methods

		#region Create

		public static Entities.Template CreateTemplate(string name)
		{
			Resources.Entities.Template template = new Resources.Entities.Template();

			template.Name = name;

			mTemplateRepository.Add(template);

			return ConvertResourcesEntity(template);
		}

		#endregion

		#region Read

		public static List<Entities.Template> ReadTemplates()
		{
			bool isCached = ConfigurationManager.CacheExpirations.IsCachingUsed;

			if (isCached && CacheHandler.GetAccessLogClone().ContainsKey(CACHEKEY_TEMPLATES))
			{
				return CacheHandler.Retrieve<List<Entities.Template>>(CACHEKEY_TEMPLATES);
			}

			List<Entities.Template> templates = ConvertResourcesEntityList(mTemplateRepository.GetTemplates());

			if (isCached)
			{
				CacheHandler.Store<List<Entities.Template>>(CACHEKEY_TEMPLATES, templates, ConfigurationManager.CacheExpirations.Warehouse.Templates);

				Dictionary<int, Entities.Template> indexId = new Dictionary<int, Entities.Template>();
				Dictionary<string, Entities.Template> indexName = new Dictionary<string, Entities.Template>();

				foreach (Entities.Template template in templates)
				{
					indexId.Add(template.Id, template);
					indexName.Add(template.Name, template);
				}

				CacheHandler.Store<Dictionary<int, Entities.Template>>(CACHEKEY_TEMPLATES_INDEX_ID, indexId, ConfigurationManager.CacheExpirations.Warehouse.Templates);
				CacheHandler.Store<Dictionary<string, Entities.Template>>(CACHEKEY_TEMPLATES_INDEX_NAME, indexName, ConfigurationManager.CacheExpirations.Warehouse.Templates);
			}

			return templates;
		}

		public static Entities.Template ReadTemplateById(int templateId)
		{
			bool isCached = ConfigurationManager.CacheExpirations.IsCachingUsed;
			Dictionary<int, Entities.Template> index = null;

			if (isCached && CacheHandler.GetAccessLogClone().ContainsKey(CACHEKEY_TEMPLATES_INDEX_ID))
			{
				index = CacheHandler.Retrieve<Dictionary<int, Entities.Template>>(CACHEKEY_TEMPLATES_INDEX_ID);
				if (index.ContainsKey(templateId))
				{
					return index[templateId];
				}
			}

			Resources.Entities.Template resource = mTemplateRepository.GetTemplateById(templateId);
            Entities.Template template = null;
            if (resource != null)
            {
                template = ConvertResourcesEntity(resource);
            }

			if (index != null)
			{
				index.Add(templateId, template);
			}

			return template;
		}

		public static Entities.Template ReadTemplateByName(string templateName)
		{
			bool isCached = ConfigurationManager.CacheExpirations.IsCachingUsed;
			Dictionary<string, Entities.Template> index = null;

			if (isCached && CacheHandler.GetAccessLogClone().ContainsKey(CACHEKEY_TEMPLATES_INDEX_NAME))
			{
				index = CacheHandler.Retrieve<Dictionary<string, Entities.Template>>(CACHEKEY_TEMPLATES_INDEX_NAME);
				if (index.ContainsKey(templateName))
				{
					return index[templateName];
				}
			}

            Resources.Entities.Template resource = mTemplateRepository.GetTemplateByName(templateName);
            Entities.Template template = null;
            if (resource != null)
            {
                template = ConvertResourcesEntity(resource);
            }

			if (index != null)
			{
				index.Add(templateName, template);
			}

			return template;
		}

		#endregion

		#region Update

		public static void UpdateTemplate(Entities.Template template)
		{
			mTemplateRepository.Update(template);
		}

		#endregion

		#region Delete

		public static void DeleteTemplate(int templateId)
		{
			mTemplateRepository.Remove(templateId);
		}

		public static void DeleteTemplate(Entities.Template template)
		{
			DeleteTemplate(template.Id);
		}

		#endregion

		#endregion

		#region Internal converter methods

		internal static List<Entities.Template> ConvertResourcesEntityList(List<Resources.Entities.Template> list)
		{
			return list.ConvertAll<Entities.Template>(new Converter<Resources.Entities.Template, Entities.Template>(ConvertResourcesEntity));
		}

		internal static Entities.Template ConvertResourcesEntity(Resources.Entities.Template template)
		{
			return new Entities.Template(template);
		}

		#endregion

	}

}